"""
工作流类型定义

定义工作流系统中的核心数据结构和枚举类型。
"""

from typing import Dict, List, Any, Optional, Callable, Union
from datetime import datetime, timedelta
from enum import Enum
from dataclasses import dataclass, field
import uuid


class WorkflowType(Enum):
    """工作流类型"""
    DATA_PROCESSING = "data_processing"         # 数据处理流程
    ANALYSIS_DECISION = "analysis_decision"     # 分析决策流程
    TRADING_EXECUTION = "trading_execution"     # 交易执行流程
    MONITORING_REPORTING = "monitoring_reporting"  # 监控报告流程
    RISK_MANAGEMENT = "risk_management"         # 风险管理流程
    COMPLIANCE_CHECK = "compliance_check"       # 合规检查流程
    CUSTOM = "custom"                          # 自定义流程


class WorkflowStatus(Enum):
    """工作流状态"""
    PENDING = "pending"         # 待执行
    RUNNING = "running"         # 执行中
    PAUSED = "paused"          # 暂停
    COMPLETED = "completed"     # 已完成
    FAILED = "failed"          # 失败
    CANCELLED = "cancelled"     # 已取消
    TIMEOUT = "timeout"        # 超时


class NodeType(Enum):
    """节点类型"""
    START = "start"             # 开始节点
    END = "end"                # 结束节点
    TASK = "task"              # 任务节点
    DECISION = "decision"       # 决策节点
    PARALLEL = "parallel"       # 并行节点
    MERGE = "merge"            # 合并节点
    CONDITION = "condition"     # 条件节点
    LOOP = "loop"              # 循环节点
    SUBPROCESS = "subprocess"   # 子流程节点


class EdgeType(Enum):
    """边类型"""
    SEQUENCE = "sequence"       # 顺序边
    CONDITION = "condition"     # 条件边
    PARALLEL = "parallel"       # 并行边
    LOOP = "loop"              # 循环边
    EXCEPTION = "exception"     # 异常边


@dataclass
class WorkflowNode:
    """工作流节点"""
    node_id: str
    name: str
    node_type: NodeType
    description: Optional[str] = None
    
    # 执行配置
    executor: Optional[str] = None  # 执行器标识
    timeout: Optional[timedelta] = None
    retry_count: int = 0
    retry_delay: timedelta = field(default_factory=lambda: timedelta(seconds=30))
    
    # 节点参数
    parameters: Dict[str, Any] = field(default_factory=dict)
    input_schema: Dict[str, Any] = field(default_factory=dict)
    output_schema: Dict[str, Any] = field(default_factory=dict)
    
    # 条件配置（用于决策节点）
    conditions: List[Dict[str, Any]] = field(default_factory=list)
    
    # 并行配置（用于并行节点）
    parallel_branches: List[str] = field(default_factory=list)
    
    # 循环配置（用于循环节点）
    loop_condition: Optional[str] = None
    max_iterations: int = 100
    
    # 元数据
    metadata: Dict[str, Any] = field(default_factory=dict)
    created_at: datetime = field(default_factory=datetime.now)
    updated_at: datetime = field(default_factory=datetime.now)


@dataclass
class WorkflowEdge:
    """工作流边"""
    edge_id: str
    source_node_id: str
    target_node_id: str
    edge_type: EdgeType
    
    # 条件配置
    condition: Optional[str] = None
    condition_params: Dict[str, Any] = field(default_factory=dict)
    
    # 数据映射
    data_mapping: Dict[str, str] = field(default_factory=dict)
    
    # 元数据
    metadata: Dict[str, Any] = field(default_factory=dict)
    created_at: datetime = field(default_factory=datetime.now)


@dataclass
class WorkflowDefinition:
    """工作流定义"""
    workflow_id: str
    name: str
    workflow_type: WorkflowType
    version: str = "1.0.0"
    description: Optional[str] = None
    
    # 节点和边
    nodes: Dict[str, WorkflowNode] = field(default_factory=dict)
    edges: List[WorkflowEdge] = field(default_factory=list)
    
    # 流程配置
    start_node_id: Optional[str] = None
    end_node_ids: List[str] = field(default_factory=list)
    
    # 执行配置
    timeout: Optional[timedelta] = None
    max_concurrent_instances: int = 10
    retry_policy: Dict[str, Any] = field(default_factory=dict)
    
    # 输入输出定义
    input_schema: Dict[str, Any] = field(default_factory=dict)
    output_schema: Dict[str, Any] = field(default_factory=dict)
    
    # 变量定义
    variables: Dict[str, Any] = field(default_factory=dict)
    
    # 元数据
    tags: List[str] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)
    created_at: datetime = field(default_factory=datetime.now)
    updated_at: datetime = field(default_factory=datetime.now)
    created_by: Optional[str] = None
    
    def add_node(self, node: WorkflowNode) -> None:
        """添加节点"""
        self.nodes[node.node_id] = node
        self.updated_at = datetime.now()
    
    def add_edge(self, edge: WorkflowEdge) -> None:
        """添加边"""
        self.edges.append(edge)
        self.updated_at = datetime.now()
    
    def get_node(self, node_id: str) -> Optional[WorkflowNode]:
        """获取节点"""
        return self.nodes.get(node_id)
    
    def get_edges_from_node(self, node_id: str) -> List[WorkflowEdge]:
        """获取从指定节点出发的边"""
        return [edge for edge in self.edges if edge.source_node_id == node_id]
    
    def get_edges_to_node(self, node_id: str) -> List[WorkflowEdge]:
        """获取指向指定节点的边"""
        return [edge for edge in self.edges if edge.target_node_id == node_id]
    
    def validate(self) -> List[str]:
        """验证工作流定义"""
        errors = []
        
        # 检查开始节点
        if not self.start_node_id:
            errors.append("缺少开始节点")
        elif self.start_node_id not in self.nodes:
            errors.append(f"开始节点 {self.start_node_id} 不存在")
        
        # 检查结束节点
        if not self.end_node_ids:
            errors.append("缺少结束节点")
        else:
            for end_node_id in self.end_node_ids:
                if end_node_id not in self.nodes:
                    errors.append(f"结束节点 {end_node_id} 不存在")
        
        # 检查边的有效性
        for edge in self.edges:
            if edge.source_node_id not in self.nodes:
                errors.append(f"边 {edge.edge_id} 的源节点 {edge.source_node_id} 不存在")
            if edge.target_node_id not in self.nodes:
                errors.append(f"边 {edge.edge_id} 的目标节点 {edge.target_node_id} 不存在")
        
        # 检查节点连通性
        reachable_nodes = self._get_reachable_nodes()
        unreachable_nodes = set(self.nodes.keys()) - reachable_nodes
        if unreachable_nodes:
            errors.append(f"存在不可达节点: {unreachable_nodes}")
        
        return errors
    
    def _get_reachable_nodes(self) -> set:
        """获取从开始节点可达的所有节点"""
        if not self.start_node_id:
            return set()
        
        visited = set()
        stack = [self.start_node_id]
        
        while stack:
            current_node = stack.pop()
            if current_node in visited:
                continue
            
            visited.add(current_node)
            
            # 添加所有可达的下一个节点
            for edge in self.get_edges_from_node(current_node):
                if edge.target_node_id not in visited:
                    stack.append(edge.target_node_id)
        
        return visited


@dataclass
class WorkflowContext:
    """工作流执行上下文"""
    instance_id: str
    workflow_definition: WorkflowDefinition
    
    # 执行状态
    status: WorkflowStatus = WorkflowStatus.PENDING
    current_node_id: Optional[str] = None
    
    # 数据上下文
    input_data: Dict[str, Any] = field(default_factory=dict)
    output_data: Dict[str, Any] = field(default_factory=dict)
    variables: Dict[str, Any] = field(default_factory=dict)
    
    # 执行历史
    execution_history: List[Dict[str, Any]] = field(default_factory=list)
    node_results: Dict[str, Any] = field(default_factory=dict)
    
    # 错误信息
    error_message: Optional[str] = None
    error_details: Dict[str, Any] = field(default_factory=dict)
    
    # 时间信息
    started_at: Optional[datetime] = None
    completed_at: Optional[datetime] = None
    
    # 元数据
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    def set_variable(self, name: str, value: Any) -> None:
        """设置变量"""
        self.variables[name] = value
    
    def get_variable(self, name: str, default: Any = None) -> Any:
        """获取变量"""
        return self.variables.get(name, default)
    
    def add_execution_record(self, record: Dict[str, Any]) -> None:
        """添加执行记录"""
        record["timestamp"] = datetime.now()
        self.execution_history.append(record)
    
    def set_node_result(self, node_id: str, result: Any) -> None:
        """设置节点执行结果"""
        self.node_results[node_id] = result
    
    def get_node_result(self, node_id: str) -> Any:
        """获取节点执行结果"""
        return self.node_results.get(node_id)
    
    def get_execution_duration(self) -> Optional[timedelta]:
        """获取执行时长"""
        if self.started_at and self.completed_at:
            return self.completed_at - self.started_at
        elif self.started_at:
            return datetime.now() - self.started_at
        return None


@dataclass
class WorkflowInstance:
    """工作流实例"""
    instance_id: str
    workflow_definition: WorkflowDefinition
    context: WorkflowContext
    
    # 实例配置
    priority: int = 0
    max_execution_time: Optional[timedelta] = None
    
    # 调度信息
    scheduled_at: Optional[datetime] = None
    
    # 创建信息
    created_at: datetime = field(default_factory=datetime.now)
    created_by: Optional[str] = None
    
    # 标签和元数据
    tags: List[str] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    @classmethod
    def create(
        cls,
        workflow_definition: WorkflowDefinition,
        input_data: Optional[Dict[str, Any]] = None,
        instance_id: Optional[str] = None,
        **kwargs
    ) -> "WorkflowInstance":
        """创建工作流实例"""
        if instance_id is None:
            instance_id = str(uuid.uuid4())
        
        context = WorkflowContext(
            instance_id=instance_id,
            workflow_definition=workflow_definition,
            input_data=input_data or {}
        )
        
        return cls(
            instance_id=instance_id,
            workflow_definition=workflow_definition,
            context=context,
            **kwargs
        )
    
    def is_running(self) -> bool:
        """检查是否正在运行"""
        return self.context.status == WorkflowStatus.RUNNING
    
    def is_completed(self) -> bool:
        """检查是否已完成"""
        return self.context.status in [
            WorkflowStatus.COMPLETED,
            WorkflowStatus.FAILED,
            WorkflowStatus.CANCELLED,
            WorkflowStatus.TIMEOUT
        ]
    
    def get_progress(self) -> float:
        """获取执行进度（0.0-1.0）"""
        total_nodes = len(self.workflow_definition.nodes)
        if total_nodes == 0:
            return 1.0
        
        executed_nodes = len(self.context.node_results)
        return min(executed_nodes / total_nodes, 1.0)


# 工作流执行器接口
class WorkflowExecutor:
    """工作流执行器基类"""
    
    async def execute_node(
        self,
        node: WorkflowNode,
        context: WorkflowContext
    ) -> Any:
        """
        执行节点
        
        Args:
            node: 要执行的节点
            context: 工作流上下文
            
        Returns:
            节点执行结果
        """
        raise NotImplementedError
    
    async def evaluate_condition(
        self,
        condition: str,
        context: WorkflowContext
    ) -> bool:
        """
        评估条件
        
        Args:
            condition: 条件表达式
            context: 工作流上下文
            
        Returns:
            条件评估结果
        """
        raise NotImplementedError


# 工作流监听器接口
class WorkflowListener:
    """工作流监听器基类"""
    
    async def on_workflow_started(self, instance: WorkflowInstance) -> None:
        """工作流开始时调用"""
        pass
    
    async def on_workflow_completed(self, instance: WorkflowInstance) -> None:
        """工作流完成时调用"""
        pass
    
    async def on_workflow_failed(self, instance: WorkflowInstance, error: Exception) -> None:
        """工作流失败时调用"""
        pass
    
    async def on_node_started(self, instance: WorkflowInstance, node: WorkflowNode) -> None:
        """节点开始执行时调用"""
        pass
    
    async def on_node_completed(self, instance: WorkflowInstance, node: WorkflowNode, result: Any) -> None:
        """节点完成执行时调用"""
        pass
    
    async def on_node_failed(self, instance: WorkflowInstance, node: WorkflowNode, error: Exception) -> None:
        """节点执行失败时调用"""
        pass